﻿using System;
using System.IO;
using System.IO.Compression;
using System.Text.RegularExpressions;
using System.Web;

namespace ChannelVN.Cached.Common
{
    public class Compres
    {


        public enum CompressOptions
        {
            GZip,
            Deflate,
            None
        }

        public class WhitespaceFilter : Stream
        {
            private GZipStream _contentGZip;
            private DeflateStream _content_Deflate;
            private Stream _content;
            private CompressOptions _options;

            public WhitespaceFilter(Stream content, CompressOptions options)
            {
                if (options == CompressOptions.GZip)
                {
                    this._contentGZip = new GZipStream(content, CompressionMode.Compress);
                    this._content = this._contentGZip;
                }
                else if (options == CompressOptions.Deflate)
                {
                    this._content_Deflate = new DeflateStream(content,
                          CompressionMode.Compress);
                    this._content = this._content_Deflate;
                }
                else
                {
                    this._content = content;
                }
                this._options = options;
            }


            public override bool CanRead
            {
                get { return this._content.CanRead; }
            }

            public override bool CanSeek
            {
                get { return this._content.CanSeek; }
            }

            public override bool CanWrite
            {
                get { return this._content.CanWrite; }
            }

            public override void Flush()
            {
                this._content.Flush();
            }

            public override long Length
            {
                get { return this._content.Length; }
            }

            public override long Position
            {
                get
                {
                    return this._content.Position;
                }
                set
                {
                    this._content.Position = value;
                }
            }

            public override int Read(byte[] buffer, int offset, int count)
            {
                return this._content.Read(buffer, offset, count);
            }

            public override long Seek(long offset, SeekOrigin origin)
            {
                return this._content.Seek(offset, origin);
            }

            public override void SetLength(long value)
            {
                this._content.SetLength(value);
            }

            public override void Write(byte[] buffer, int offset, int count)
            {
                byte[] data = new byte[count + 1];
                Buffer.BlockCopy(buffer, offset, data, 0, count);
                string s = System.Text.Encoding.UTF8.GetString(data);

                //var regRemoveSpace  = new Regex("[\\s\\t\\n\\r]+");
                var regRemoveComment = new Regex("\\s+//[^\\n\\r]+[\\n\\r]+");
                s = (new Regex("<script[^>]*>.*?</script>", RegexOptions.IgnoreCase | RegexOptions.Singleline)).Replace(s, delegate(Match m)
                {
                    return regRemoveComment.Replace(m.Groups[0].Value, string.Empty);
                });

                s = Regex.Replace(s, "^\\s*", string.Empty, RegexOptions.Compiled |
                                      RegexOptions.Multiline);
                s = Regex.Replace(s, "^\\s*", string.Empty, RegexOptions.Compiled |
                                  RegexOptions.Multiline);
                s = Regex.Replace(s, "\\r\\n", string.Empty, RegexOptions.Compiled |
                                  RegexOptions.Multiline);
                s = Regex.Replace(s, "<!--*.*?-->", string.Empty, RegexOptions.Compiled |
                                  RegexOptions.Multiline);
                //s = Regex.Replace(s, "<!--*.*?-->", string.Empty, RegexOptions.Compiled |
                //                  RegexOptions.Multiline);
                //str.replace(/(\w+)=[\'\"](.*?)[\'\"]/gi, '$1="$2" ');
                byte[] outdata = System.Text.Encoding.UTF8.GetBytes(s);
                this._content.Write(outdata, 0, outdata.GetLength(0));




                //s = Regex.Replace(s, "\\s+//[^\\n\\r]+[\\n\\r]+", string.Empty, RegexOptions.Compiled |
                //  RegexOptions.Singleline);
                //s = Regex.Replace(s, "^\\s*", string.Empty, RegexOptions.Compiled |
                //                  RegexOptions.Multiline);
                //s = Regex.Replace(s, "\\r\\n", string.Empty, RegexOptions.Compiled |
                //                  RegexOptions.Multiline);
                //s = Regex.Replace(s, "<!--*.*?-->", string.Empty, RegexOptions.Compiled |
                //                  RegexOptions.Multiline);

            }
        }


        public static void doCompression()
        {
            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;
            string acceptEncoding = request.Headers["Accept-Encoding"];
            HttpResponse response = context.Response;
            if (!string.IsNullOrEmpty(acceptEncoding))
            {
                acceptEncoding = acceptEncoding.ToUpperInvariant();
                if (acceptEncoding.Contains("GZIP"))
                {
                    response.Filter = new GZipStream(context.Response.Filter,
                    CompressionMode.Compress);
                    response.AppendHeader("Content-encoding", "gzip");
                }
                else if (acceptEncoding.Contains("DEFLATE"))
                {
                    response.Filter = new DeflateStream(context.Response.Filter,
                    CompressionMode.Compress);
                    response.AppendHeader("Content-encoding", "deflate");
                }
            }
            response.Cache.VaryByHeaders["Accept-Encoding"] = true;
        }

        public static void Compress()
        {
            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;
            string acceptEncoding = request.Headers["Accept-Encoding"];
            HttpResponse response = context.Response;
            if (!string.IsNullOrEmpty(acceptEncoding))
            {
                acceptEncoding = acceptEncoding.ToUpperInvariant();
                if (acceptEncoding.Contains("GZIP"))
                {
                    //response.Filter = new GZipStream(context.Response.Filter, 
                    //CompressionMode.Compress);
                    response.Filter = new WhitespaceFilter(context.Response.Filter,
                                      CompressOptions.GZip);
                    response.AppendHeader("Content-encoding", "gzip");
                }
                else if (acceptEncoding.Contains("DEFLATE"))
                {
                    //response.Filter = new DeflateStream(context.Response.Filter, 
                    //CompressionMode.Compress);
                    response.Filter = new WhitespaceFilter(context.Response.Filter,
                                      CompressOptions.Deflate);
                    response.AppendHeader("Content-encoding", "deflate");
                }
            }
            response.Cache.VaryByHeaders["Accept-Encoding"] = true;
        }
    }
}
